CM-62984: Add Codex CLI support to ai-guardrails#436
Open
MaorDavidzon wants to merge 4 commits intomainfrom
Open
CM-62984: Add Codex CLI support to ai-guardrails#436MaorDavidzon wants to merge 4 commits intomainfrom
MaorDavidzon wants to merge 4 commits intomainfrom
Conversation
Extend ai-guardrails hooks to cover OpenAI Codex CLI alongside Cursor and Claude Code. Installs ~/.codex/hooks.json for UserPromptSubmit, SessionStart, and PreToolUse:Bash events, and merges `[features] codex_hooks = true` into ~/.codex/config.toml while preserving existing keys. Adds a new canonical CommandExec event for Bash command scanning since Codex's PreToolUse only intercepts Bash today. CodexResponseBuilder reuses the Claude Code response shapes (Codex accepts them verbatim). Adds tomli-w (and tomli on py<3.11) as direct deps to manage the Codex TOML config safely. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Post-merge fixes after #434 (session-start refactor) landed on main: - consts.py: Codex SessionStart now calls CYCODE_SESSION_START_COMMAND with --ide codex, matching the Cursor/Claude-code pattern (the old CYCODE_ENSURE_AUTH_COMMAND constant was removed). - session_start_command.py: add Codex branch to _build_session_payload so session_start works for the Codex IDE. - handlers.py: drop ai_client.create_conversation() call from handle_before_command_exec; conversation creation now happens in the session-start command, matching the other three handlers. - test_hooks_manager.py: update Codex SessionStart test to assert on CYCODE_SESSION_START_COMMAND + --ide codex. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ilanlido
reviewed
Apr 23, 2026
| ) | ||
|
|
||
|
|
||
| def handle_before_command_exec(ctx: typer.Context, payload: AIHookPayload, policy: dict) -> dict: |
Collaborator
There was a problem hiding this comment.
pretty similar to other handlers like mcp, if we could reduce duplicate code it would be nice
| mcp_server_name: Optional[str] = None # For mcp_execution events | ||
| mcp_tool_name: Optional[str] = None # For mcp_execution events | ||
| mcp_arguments: Optional[dict] = None # For mcp_execution events | ||
| command: Optional[str] = None # For command_exec events (e.g., Codex PreToolUse:Bash) |
Comment on lines
+253
to
+255
| else: | ||
| # Unknown or unsupported event combination; fall back to raw event name | ||
| canonical_event = CODEX_EVENT_MAPPING.get(hook_event_name, hook_event_name) |
Collaborator
There was a problem hiding this comment.
what about read file / mcp?
Comment on lines
189
to
190
| elif hook_event_name == 'PreToolUse': | ||
| canonical_event = AiHookEventType.FILE_READ if tool_name == 'Read' else AiHookEventType.MCP_EXECUTION |
Collaborator
There was a problem hiding this comment.
should we add bash here?
|
|
||
|
|
||
| # IDE-specific event name mappings to canonical types | ||
| CURSOR_EVENT_MAPPING = { |
Collaborator
There was a problem hiding this comment.
does cursor has dedicated bash event?
| @@ -77,6 +87,13 @@ def _get_claude_code_hooks_dir() -> Path: | |||
| hooks_file_name='settings.json', | |||
| hook_events=['UserPromptSubmit', 'PreToolUse:Read', 'PreToolUse:mcp'], | |||
| } | ||
|
|
||
|
|
||
| def _get_codex_hooks_config(async_mode: bool = False) -> dict: |
Collaborator
There was a problem hiding this comment.
looks pretty much the same as claude, can we reduce code duplication here
| if ide == AIIDEType.CODEX: | ||
| return AIHookPayload( | ||
| conversation_id=payload.get('session_id'), | ||
| generation_id=payload.get('turn_id'), |
| mcp_servers, enabled_plugins = _get_claude_code_session_context() | ||
| elif ide == AIIDEType.CURSOR: | ||
| mcp_servers, enabled_plugins = _get_cursor_session_context() | ||
| else: |
Collaborator
There was a problem hiding this comment.
do we have mcps / plugins in codex?
|
|
||
|
|
||
| @pytest.fixture | ||
| def codex_policy() -> dict[str, Any]: |
Collaborator
There was a problem hiding this comment.
its not really specific to codex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cycode ai-guardrailsto support OpenAI Codex CLI alongside Cursor and Claude Code: installs~/.codex/hooks.jsonforUserPromptSubmit,SessionStart, andPreToolUse:Bash; auto-enables[features] codex_hooks = truein~/.codex/config.tomlwhile preserving existing keys.CommandExecevent +handle_before_command_exechandler to scan shell commands the agent is about to run for secrets — closest Codex equivalent to theFileRead/McpExecutionevents (Codex'sPreToolUsecurrently only intercepts Bash).codex_config.pysafely merges the feature flag viatomllib/tomli+tomli-w;CodexResponseBuilderreuses Claude Code response shapes verbatim (Codex accepts them).Scope note
Codex hooks intercept
UserPromptSubmitandPreToolUse:Bashonly — not MCP calls or file reads. SoFileReadandMcpExecutioncanonical events cannot be wired for Codex today. This MR ships what's possible; coverage can expand as Codex extends its hook surface.New direct deps
tomli-w(py3.9+) — TOML writer (stdlib has only a reader)tomli(py<3.11 only) — backport of stdlibtomllibTest plan
poetry run pytest tests/cli/commands/ai_guardrails/ -v— 150 passing (23 new)poetry run pytest tests/— 713 passingruff check+ruff formatclean on all touched filesscan --ide codexis skipped ({}returned)codex exec— hook fires and Codex honors the response🤖 Generated with Claude Code